package com.icexxx.mapper_gen;

import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;

public class FunctionParse {
    public static Func parse(List<String> lines) {
        if (CollUtil.isEmpty(lines)) {
            return null;
        }
        String comment = null;
        boolean start = false;
        boolean end = false;
        int indexNum = 0;
        StringBuilder funcStr = new StringBuilder();
        for (int i = 0; i < lines.size(); i++) {
            String line = lines.get(i);
            String lineTrim = line.trim();
            if (StrUtil.isBlank(line)) {
                continue;
            }
            if (start) {
                if (comment == null) {
                    String current = StrUtil.removePrefix(lineTrim, "*");
                    current = current.trim();
                    comment = current;
                }
            }
            if (indexNum == 2) {
                funcStr.append(lineTrim);
                funcStr.append(" ");
            }
            if (lineTrim.startsWith("/*")) {
                start = true;
                if (!"/**".equals(lineTrim) && !"/*".equals(lineTrim)) {
                    String current = StrUtil.removePrefix(lineTrim, "/*");
                    if (comment == null) {
                        comment = current;
                    }
                }
                indexNum++;
            }
            if (lineTrim.endsWith("*/")) {
                start = false;
                end = true;
                indexNum++;
            }
        }
        String funContent = funcStr.toString();
        Func func = parse(funContent, comment);
        return func;
    }

    private static Func parse(String funContent, String comment) {
        funContent = funContent.trim();
        funContent = StrUtil.removeSuffix(funContent, ";");
        funContent = funContent.trim();
        int leftAngleBracketsIndex = funContent.indexOf("<");
        int rightAngleBracketsIndex = funContent.indexOf(">");
        int spaceIndex = funContent.indexOf(" ");
        int leftIndex = funContent.indexOf("(");
        int rightIndex = funContent.lastIndexOf(")");
        Func func = new Func();
        if (leftAngleBracketsIndex == -1 || leftAngleBracketsIndex > leftIndex) {
            int leftParamIndex = funContent.indexOf("(");
            int rightParamIndex = funContent.lastIndexOf(")");
            String funcNamePart = funContent.substring(0, leftParamIndex);
            String funcParamPart = funContent.substring(leftParamIndex + 1, rightParamIndex);
            funcNamePart = funcNamePart.trim();
            funcParamPart = funcParamPart.trim();
            int funcSpaceIndex = funcNamePart.lastIndexOf(" ");
            String funcType = funcNamePart.substring(0, funcSpaceIndex);
            String funcName = funcNamePart.substring(funcSpaceIndex + 1);
            funcName = funcName.trim();
            String funcParam = funcParamPart.trim();
            Param paramReturn = new Param(funcType, null, funcName);
            func.setReturnParam(paramReturn);
            func.setName(funcName);
            List<Param> paramList = parseParamList(funcParam);
            func.setParamList(paramList);
        } else {
            if (rightAngleBracketsIndex != -1) {
                String left = funContent.substring(0, rightAngleBracketsIndex + 1);
                String right = funContent.substring(rightAngleBracketsIndex + 1);
                right = right.trim();
                int leftParamIndex = right.indexOf("(");
                int rightParamIndex = right.lastIndexOf(")");
                String funcName = right.substring(0, leftParamIndex);
                String funcParam = right.substring(leftParamIndex + 1, rightParamIndex);
                funcName = funcName.trim();
                funcParam = funcParam.trim();
                Param paramReturn = parseParamReturn(left);
                func.setReturnParam(paramReturn);
                func.setName(funcName);
                List<Param> paramList = parseParamList(funcParam);
                func.setParamList(paramList);
            }
        }

        func.setComment(comment);
        System.out.println("funContent = " + funContent);
        return func;
    }

    private static List<Param> parseParamList(String content) {
        List<String> splitTrim = split(content, ",");
        List<Param> list = new ArrayList<>();
        for (int i = 0; i < splitTrim.size(); i++) {
            String paramStr = splitTrim.get(i);
            Param param = new Param();
            String paramPair = paramStr;
            if (paramStr.startsWith("@Param")) {
                paramStr = StrUtil.removePrefix(paramStr, "@Param");
                paramStr = paramStr.trim();
                int rightIndex = paramStr.indexOf(")");
                paramPair = paramStr.substring(rightIndex + 1);
                paramPair = paramPair.trim();
                int leftAngleBracketsIndex = paramStr.indexOf("(");
                int rightAngleBracketsIndex = paramStr.lastIndexOf(")");
                if (leftAngleBracketsIndex != -1 && rightAngleBracketsIndex != -1) {
                    paramStr = paramStr.substring(leftAngleBracketsIndex + 1, rightAngleBracketsIndex);
                    paramStr = paramStr.trim();
                    if (paramStr.contains("\"")) {
                        paramStr = StrUtil.unWrap(paramStr, '\"');
                        paramStr = paramStr.trim();
                        param.setComment(paramStr);
                    }

                }

            }
            int lastIndexOf = paramPair.lastIndexOf(" ");
            String leftStr = paramPair.substring(0, lastIndexOf);
            String rightStr = paramPair.substring(lastIndexOf + 1);
            rightStr = rightStr.trim();
            String type = leftStr;
            if (leftStr.contains("<")) {
                int leftBookIndex = leftStr.indexOf("<");
                int rightBookIndex = leftStr.lastIndexOf(">");
                String genericity = leftStr.substring(leftBookIndex + 1, rightBookIndex);
                genericity = genericity.trim();
                genericity = genericity.replace(",  ", ",");
                genericity = genericity.replace(", ", ",");
                type = leftStr.substring(0, leftBookIndex);
                type = type.trim();
                param.setGenericity(genericity);
            }
            param.setType(type);
            param.setName(rightStr);
            list.add(param);
        }
        return list;
    }

    private static Param parseParamReturn(String left) {
        left = left.replace(",  ", ",");
        left = left.replace(", ", ",");
        int leftAngleBracketsIndex = left.indexOf("<");
        int rightAngleBracketsIndex = left.lastIndexOf(">");
        Param param = new Param();
        String name = left;
        if (leftAngleBracketsIndex != -1) {
            name = left.substring(0, leftAngleBracketsIndex);
            name = name.trim();
            name = left.substring(0, leftAngleBracketsIndex);
            String genericity = left.substring(leftAngleBracketsIndex + 1, rightAngleBracketsIndex);
            genericity = genericity.trim();
            param.setGenericity(genericity);
        }
        param.setType(name);
        return param;
    }

    private static List<String> split(String str, String separator) {
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        List<String> result = new ArrayList<>();
        char[] chs = str.toCharArray();
        int stack = 0;
        for (int i = 0; i < chs.length; i++) {
            char ch = chs[i];
            boolean addFlag = true;
            if (ch == '<') {
                stack++;
            } else if (ch == '>') {
                stack--;
            }
            if (stack == 0 && ch == ',') {
                String part = sb.toString();
                list.add(part);
                sb = new StringBuilder();
                addFlag = false;
            }
            if (addFlag) {
                sb.append(ch);
            }
        }
        String part = sb.toString();
        if (part != null && !"".equals(part)) {
            list.add(part);
        }
        String[] strs = new String[list.size()];
        for (int i = 0; i < strs.length; i++) {
            String cur = list.get(i);
            if (cur != null && !"".equals(cur)) {
                result.add(cur.trim());
            }
        }
        return result;
    }
}
